package com.sc.nft.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.admin.request.*;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.MarketTypeEnum;
import com.sc.nft.enums.PayMethodEnum;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.exception.ModelException;
import com.sc.nft.pool.SysMemberPool;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/maintain/buy")
@Api(tags = "市场市值账号后台抢购")
public class MaintainBuyController {
    private final SecondCollectionConfigDao secondCollectionConfigDao;
    private final MarketMaintainDao marketMaintainDao;
    private final NewSecondCollectionCommonService newSecondCollectionCommonService;
    private final UserCollectionDao userCollectionDao;
    private final UserInfoDao userInfoDao;
    private final RedissonClient redissonClient;
    private final PayOrderService payOrderService;
    private final StaticDataService staticDataService;
    private final DigitalCollectionDao digitalCollectionDao;
    private final ExitConsensusUserDao exitConsensusUserDao;
    private final SecondOrderDao secondOrderDao;
    private final SecondCollectionService secondCollectionService;
    private final SecondCollectionDao secondCollectionDao;
    private final UserCollectionService userCollectionService;
    private final SearchRelevanceDao searchRelevanceDao;
/*
    1.商品列表,商品名字+价格
    3.自己的藏品列表
    4.购买.(不要密码,输入购买数量,直接去数据库里面获取数据让后进行调用处理)
    5.一键挂单
    6.一键取消寄售
 */

    @ApiOperation(value = "品牌列表 后端市值账号,用来扫货收货使用.其他地方禁止使用.", notes = "品牌列表 后端市值账号,用来扫货收货使用.其他地方禁止使用.", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/brandConfigList", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<BrandConfigAdminVO>> brandConfigList() {
        return Result.success(secondCollectionConfigDao.brandConfigList());
    }

//    @ApiOperation(value = "自由市场 后端市值账号,用来扫货收货使用.其他地方禁止使用.", notes = "自由市场 后端市值账号,用来扫货收货使用.其他地方禁止使用.", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
//    @PostMapping(value = "/v3.7/freeMarketList", produces = MediaType.APPLICATION_JSON_VALUE)
//    @SysMemberLogin
//    public Result<List<SecondCollectionConfigListVO>> collectionPagev3_7List() {
//        return Result.success(secondCollectionConfigDao.freeMarketPagev3_7List());
//    }

    @ApiOperation(value = "市值账号我的藏品", notes = "市值账号我的藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/myCollectionNow", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<MyCollectionNowListVO>> getUserInviteListNow(@RequestBody IdRequest idRequest) {
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), idRequest.getId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        return Result.success(userCollectionDao.getUserInviteListNow(idRequest.getId()));
    }


    @ApiOperation(value = "市值账号和后台关联", notes = "市值账号和后台关联", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/marketMaintainUsers", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<MarketMaintainUserVO>> marketMaintainUsers() {
        return Result.success(marketMaintainDao.marketMaintainUsers(SysMemberPool.getMember().getId()));
    }


    @ApiOperation(value = "一键下单", notes = "一键下单", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/oneClickOrder", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result oneClickOrder(@RequestBody OneClickOrderDTO oneClickOrderDTO) {
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), oneClickOrderDTO.getUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        if (oneClickOrderDTO.getSum() > 100) {
            throw new GlobalRunTimeException("单次下单不要超过100单");
        }
        LockOrderVO lockOrderVO;
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(oneClickOrderDTO.getUserId());
        // 对应用户数据要手动写入当前线程内.
        // 调用新的锁单接口
        SecondBrandCollectionLockOrderDTO request = new SecondBrandCollectionLockOrderDTO();
        request.setCollectionId(oneClickOrderDTO.getCollectionId());
        request.setBuyCount(oneClickOrderDTO.getSum());
        lockOrderVO = newSecondCollectionCommonService.lockBrandOrder(userInfo, request);
        GetPaySignVO paySecond = payOrderService.getPaySecond(PayMethodEnum.WALLET_PAY, lockOrderVO.getOrderIds(),
                null, userInfo, "127.0.0.1", null, false, null, null);
        payOrderService.verifyPay(userInfo, paySecond.getId(), userInfo.getTransactionPassword(), null, null);
        return Result.success(lockOrderVO);
    }


    @ApiOperation(value = "一键下架", notes = "一键下架", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/oneClickOffTheShelf", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result oneClickOffTheShelf(@RequestBody OneClickOffTheShelfDTO oneClickOffTheShelfDTO) {
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), oneClickOffTheShelfDTO.getUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(oneClickOffTheShelfDTO.getUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);
        try {
            Page<MySalestListVO> mySalestListVOPage = newSecondCollectionCommonService.mySalestList(UserPool.getUser(), 1, oneClickOffTheShelfDTO.getSum());
            List<MySalestListVO> records = mySalestListVOPage.getRecords();
            SaveBatchCancellationConsignmentDTO saveBatchCancellationConsignmentDTO = new SaveBatchCancellationConsignmentDTO();
            List<Long> collect = records.stream().map(MySalestListVO::getUserCollectionId).collect(Collectors.toList());
            saveBatchCancellationConsignmentDTO.setList(collect);
            saveBatchCancellationConsignmentDTO.setDealPwd(userInfo.getTransactionPassword());
            newSecondCollectionCommonService.saveBatchCancellationConsignment(saveBatchCancellationConsignmentDTO);
        } finally {
            UserPool.clear();
        }
        return Result.success();
    }


    @ApiOperation(value = "一键上架", notes = "一键上架", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/oneClickShelf", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result oneClickShelf(@RequestBody OneClickShelfDTO oneClickShelfDTO) {
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), oneClickShelfDTO.getUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(oneClickShelfDTO.getUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);

        // 获取自己没有上架的藏品列表,让后获取前面几个,批量上锁且上架.

        try {
            SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionIdAndStatus(oneClickShelfDTO.getCollectionId());
            if (ObjectUtil.isNull(secondCollectionConfig)) {
                return PageResult.fail(ErrorCode.NOT_CON_SIGN);
            }

            if (secondCollectionConfig.getMarketType() != MarketTypeEnum.BRAND_INCUBATION) {
                throw new GlobalRunTimeException(ErrorCode.PARAM_ERROR);
            }

            SecondConsignDetailAndListVO secondConsignDetailAndListVO = new SecondConsignDetailAndListVO();
            DigitalCollection digitalCollection = digitalCollectionDao.getById(secondCollectionConfig.getCollectionId());
            secondConsignDetailAndListVO.setId(digitalCollection.getId());
            secondConsignDetailAndListVO.setFirstTitle(digitalCollection.getFirstTitle());
            secondConsignDetailAndListVO.setCreationContent(digitalCollection.getCreationContent());
            // 2022年11月7日16:05:51 最新成交价修改
            BigDecimal newDeal = digitalCollection.getNewDeal();
            //最新成交价
            BigDecimal newPrice = secondOrderDao.getLastPrice(digitalCollection.getId());
            newPrice = ObjectUtil.isNull(newPrice) ? BigDecimal.ZERO : newPrice;
            //藏品发售价
            BigDecimal issuePrice = digitalCollection.getIssuePrice();
            issuePrice = ObjectUtil.isNull(issuePrice) ? BigDecimal.ZERO : issuePrice;

            // 2022年11月7日16:05:51 最新成交价修改
            secondConsignDetailAndListVO.setFinalPrice(digitalCollection.getNewDeal().toPlainString());
            secondConsignDetailAndListVO.setIssuePrice(issuePrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            secondConsignDetailAndListVO.setMinPrice(secondCollectionConfig.getMinPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            secondConsignDetailAndListVO.setMaxPrice(secondCollectionConfig.getMaxPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            secondConsignDetailAndListVO.setSumCount(digitalCollection.getSumCount());
            secondConsignDetailAndListVO.setCollectionListVOList(userCollectionDao.getConsignCollectionListAdmin(UserPool.getUser().getId(), oneClickShelfDTO.getCollectionId(), oneClickShelfDTO.getSum()));
            secondConsignDetailAndListVO.setNewDeal(newDeal.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            // 以上是直接复制来的获取可以寄售的藏品列表内容数据

            // 批量进行上架验证,加锁
            List<ConsignCollectionListVO> collectionListVOList = secondConsignDetailAndListVO.getCollectionListVOList();
            if (CollUtil.isEmpty(collectionListVOList)) {
                return Result.fail("当前上架藏品数量不存在");
            }
            RLock lock = redissonClient.getLock(RedisKeyEnum.CON_SIGN.getKey() + collectionListVOList.get(0));
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                //获取寄售时间 并且判断是否是在寄售时间内
                StaticData staticData = staticDataService.getByType("market_config");
                if (ObjectUtil.isNull(staticData) || StrUtil.isBlank(staticData.getValue())) {
                    return Result.fail(ErrorCode.NOT_ALLOW_DEAL_TIME);
                }
                DateTime now = DateTime.now();
                String dateStr = now.toString("yyyy-MM-dd");
                MarketConfigDTO marketConfigDTO = JSONObject.parseObject(staticData.getValue(), MarketConfigDTO.class);
                DateTime billingStartDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeOne(), "yyyy-MM-dd HH:mm");
                DateTime billingEndDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeOne(), "yyyy-MM-dd HH:mm");
                DateTime billingStartDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeTwo(), "yyyy-MM-dd HH:mm");
                DateTime billingEndDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeTwo(), "yyyy-MM-dd HH:mm");

                if (!((now.after(billingStartDate1) && now.before(billingEndDate1)) || (now.after(billingStartDate2) && now.before(billingEndDate2)))) {
                    return Result.fail(ErrorCode.NOT_ALLOW_DEAL_TIME);
                }

                secondCollectionService.batchConSign(collectionListVOList.stream().map(ConsignCollectionListVO::getId).collect(Collectors.toList()), Convert.toBigDecimal(secondConsignDetailAndListVO.getMaxPrice()), userInfo.getTransactionPassword());
            } else {
                throw new GlobalRunTimeException(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            UserPool.clear();
        }

        return Result.success();
    }

    @PostMapping(value = "/maintainCollectionList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "市值账号挂单信息(排除当前选中的市值账号)", notes = "市值账号挂单信息(排除当前选中的市值账号)",
            httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<IPage<MaintainUserConSignCollectionPageDTO>> maintainCollectionList(@RequestBody MaintainSecondCollectionListRequest request) {
        //基础校验
        this.validMaintainCollectionListRequest(request);
        //绑定权限校验
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        return Result.success(secondCollectionService.getMainTainConSignCollection(request.getPageNo()
                , request.getPageSize(), request.getCheckedUserId(), request.getLowPrice(), request.getHighPrice(), request.getCollectionId()));
    }


    @PostMapping(value = "/maintainBuySecondCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "市值账号购买二级藏品(单买)", notes = "市值账号购买二级藏品(单买)",
            httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<?> maintainBuySecondCollection(@RequestBody MaintainBuySecondCollectionRequest request) {
        //参数校验
        validMaintainBuySecondCollectionRequest(request);
        //绑定权限校验
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        //下单流程
        SecondCollection secondCollection = secondCollectionDao.findById(request.getId());
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(request.getCheckedUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);
        // 对应用户数据要手动写入当前线程内.
        // 调用新的锁单接口
        NewSecondCollectionLockOrder newSecondCollectionLockOrder = new NewSecondCollectionLockOrder();
        newSecondCollectionLockOrder.setSecondCollectionIds(Lists.newArrayList(secondCollection.getId()));
        newSecondCollectionLockOrder.setCollectionId(secondCollection.getCollectionId());
        newSecondCollectionLockOrder.setMarketType(secondCollection.getMarketType());
        List<RLock> lock = new ArrayList();
        try {
            // 用来存放被锁的id
            List<Long> mallLockId = new ArrayList<>();
            newSecondCollectionLockOrder.getSecondCollectionIds().forEach(aLong -> {
                // lock的key组成  LOCK_ORDER挂售id
                String key = StrUtil.format("LOCK_ORDER:{}", aLong);
                RLock orderLock = redissonClient.getLock(key);
                log.info("二级锁单Key:{}", orderLock);
                boolean heldByCurrentThread = orderLock.tryLock();
                if (!heldByCurrentThread) {
                    // 把挂载的商品id返回去.
                    mallLockId.add(aLong);
                } else {
                    lock.add(orderLock);
                }
            });
            if (CollUtil.isNotEmpty(mallLockId)) {
                throw new ModelException(mallLockId, ErrorCode.COUNT_NOT_ENOUGH);
            }
            LockOrderVO lockOrderVO = newSecondCollectionCommonService.lockOrder(userInfo, newSecondCollectionLockOrder);
            GetPaySignVO paySecond = payOrderService.getPaySecond(PayMethodEnum.WALLET_PAY, lockOrderVO.getOrderIds(),
                    null, userInfo, "127.0.0.1", null, false, null, null);
            payOrderService.verifyPay(userInfo, paySecond.getId(), userInfo.getTransactionPassword(), null, null);
        } finally {
            // 批量释放锁
            lock.forEach(rLock -> {
                rLock.unlock();
                log.info("二级释放Key:{}", rLock);
            });
            UserPool.clear();
        }
        return Result.success();
    }

    @PostMapping(value = "/batchBuySecondCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "市值账号批量购买二级藏品", notes = "市值账号批量购买二级藏品",
            httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<?> batchBuySecondCollection(@RequestBody MaintainBatchSecondCollectionRequest request) {
        //参数校验
        validBatchMaintainSecondCollectionRequest(request);
        //绑定权限校验
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        //查询价格排序较低的订单
        List<Long> ids = secondCollectionDao.getCollectionIdsByMaintainUser(request.getCheckedUserId(),
                request.getCollectionId(), request.getNum(), request.getLowPrice(), request.getHighPrice());
        if (ids.isEmpty()) {
            throw new GlobalRunTimeException("当前藏品没有可购买挂单");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(request.getCheckedUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);
        // 对应用户数据要手动写入当前线程内.
        // 调用新的锁单接口
        NewSecondCollectionLockOrder newSecondCollectionLockOrder = new NewSecondCollectionLockOrder();
        newSecondCollectionLockOrder.setSecondCollectionIds(ids);
        newSecondCollectionLockOrder.setCollectionId(request.getCollectionId());
        newSecondCollectionLockOrder.setMarketType(MarketTypeEnum.FREE_MARKET);
        List<RLock> lock = new ArrayList();
        try {
            // 用来存放被锁的id
            List<Long> mallLockId = new ArrayList<>();
            newSecondCollectionLockOrder.getSecondCollectionIds().forEach(aLong -> {
                // lock的key组成  LOCK_ORDER挂售id
                String key = StrUtil.format("LOCK_ORDER:{}", aLong);
                RLock orderLock = redissonClient.getLock(key);
                log.info("二级锁单Key:{}", orderLock);
                boolean heldByCurrentThread = orderLock.tryLock();
                if (!heldByCurrentThread) {
                    // 把挂载的商品id返回去.
                    mallLockId.add(aLong);
                } else {
                    lock.add(orderLock);
                }
            });
            if (CollUtil.isNotEmpty(mallLockId)) {
                throw new ModelException(mallLockId, ErrorCode.COUNT_NOT_ENOUGH);
            }
            LockOrderVO lockOrderVO = newSecondCollectionCommonService.lockOrder(userInfo, newSecondCollectionLockOrder);
            GetPaySignVO paySecond = payOrderService.getPaySecond(PayMethodEnum.WALLET_PAY, lockOrderVO.getOrderIds(),
                    null, userInfo, "127.0.0.1", null, false, null, null);
            payOrderService.verifyPay(userInfo, paySecond.getId(), userInfo.getTransactionPassword(), null, null);
        } finally {
            // 批量释放锁
            lock.forEach(rLock -> {
                rLock.unlock();
                log.info("二级释放Key:{}", rLock);
            });
            UserPool.clear();
        }
        return Result.success();
    }


    @PostMapping(value = "/maintainHoldCollectionList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "市值账号藏品列表", notes = "市值账号藏品列表",
            httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<Page<MyCollectionListByCollectionIdVO>> maintainHoldCollectionList(@RequestBody MaintainCollectionListRequest request) {
        //参数校验
        validMaintainCollectionRequest(request);
        //绑定权限校验
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        return Result.success(userCollectionService.maintainCollectionListByCollectionId(request.getCollectionId(),
                request.getCheckedUserId(), request.getPageNo(), request.getPageSize(), request.getLowPrice(),
                request.getHighPrice(), request.getOnConsign()));
    }

    @PostMapping(value = "/maintainFreeMarketHitShelf", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "单个上架", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<?> freeMarketHitShelf(@Valid @RequestBody MaintainFreeMarketHitShelfRequest request) {
        //绑定权限校验
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(request.getCheckedUserId());

        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);

        //参数校验
        validMaintainFreeMarketHitShelf(request);

        Map map = new HashedMap();
        try {
            Boolean is = newSecondCollectionCommonService.freeMarketHitShelf(request.getUserCollectionId(),
                    request.getSalesPrice(), userInfo.getTransactionPassword());
            map.put("execute", is);
        } finally {
            UserPool.clear();
        }

        return Result.success(map);
    }

    @ApiOperation(value = "市值账号批量下架自由市场藏品", notes = "市值账号批量下架自由市场藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/maintainBatchOffTheShelf", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<?> batchOffTheShelf(@RequestBody MaintainBatchOffTheShelfRequest request) {
        //基础校验
        validMaintainFreeMarketBatchOffShelf(request);
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(request.getCheckedUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);
        try {
            List<MySalestListVO> records = newSecondCollectionCommonService.maintainSalestList(UserPool.getUser(),
                    request.getCollectionId(), request.getLowPrice(), request.getHighPrice());
            SaveBatchCancellationConsignmentDTO saveBatchCancellationConsignmentDTO = new SaveBatchCancellationConsignmentDTO();
            List<Long> collect = records.stream().map(MySalestListVO::getUserCollectionId).collect(Collectors.toList());
            saveBatchCancellationConsignmentDTO.setList(collect);
            saveBatchCancellationConsignmentDTO.setDealPwd(userInfo.getTransactionPassword());
            newSecondCollectionCommonService.saveBatchCancellationConsignment(saveBatchCancellationConsignmentDTO);
        } finally {
            UserPool.clear();
        }
        return Result.success();
    }

    @ApiOperation(value = "市值账号下架单个自由市场藏品", notes = "市值账号下架单个自由市场藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/maintainOffTheShelf", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<?> OffTheShelf(@RequestBody MaintainOffTheShelfRequest request) {
        //基础校验
        validMaintainFreeMarketOffShelf(request);
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(request.getCheckedUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);
        try {
            SaveBatchCancellationConsignmentDTO saveBatchCancellationConsignmentDTO = new SaveBatchCancellationConsignmentDTO();
            List<Long> collect = Lists.newArrayList(request.getUserCollectionId());
            saveBatchCancellationConsignmentDTO.setList(collect);
            saveBatchCancellationConsignmentDTO.setDealPwd(userInfo.getTransactionPassword());
            newSecondCollectionCommonService.saveBatchCancellationConsignment(saveBatchCancellationConsignmentDTO);
        } finally {
            UserPool.clear();
        }
        return Result.success();
    }

    @ApiOperation(value = "市值账号批量上架自由市场藏品", notes = "市值账号批量上架自由市场藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/maintainBatchOnTheShelf", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<?> batchOnTheShelf(@RequestBody MaintainBatchOnTheShelfRequest request) {
        //基础教研
        validMaintainFreeMarketBatchHitShelf(request);
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        // 先获取列表.在把所有获取到的数据加锁,加锁后.把所有数据调用方法进行下单.
        UserInfo userInfo = userInfoDao.getById(request.getCheckedUserId());
        // 对应用户数据要手动写入当前线程内.
        UserPool.setUser(userInfo);

        // 获取自己没有上架的藏品列表,让后获取前面几个,批量上锁且上架.

        try {
            SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionIdAndStatus(request.getCollectionId());
            if (ObjectUtil.isNull(secondCollectionConfig)) {
                return PageResult.fail(ErrorCode.NOT_CON_SIGN);
            }

            if (secondCollectionConfig.getMarketType() != MarketTypeEnum.FREE_MARKET) {
                throw new GlobalRunTimeException(ErrorCode.PARAM_ERROR);
            }

            SecondConsignDetailAndListVO secondConsignDetailAndListVO = new SecondConsignDetailAndListVO();
            DigitalCollection digitalCollection = digitalCollectionDao.getById(secondCollectionConfig.getCollectionId());
            secondConsignDetailAndListVO.setId(digitalCollection.getId());
            secondConsignDetailAndListVO.setFirstTitle(digitalCollection.getFirstTitle());
            secondConsignDetailAndListVO.setCreationContent(digitalCollection.getCreationContent());
            // 2022年11月7日16:05:51 最新成交价修改
            BigDecimal newDeal = digitalCollection.getNewDeal();
            //最新成交价
            BigDecimal newPrice = secondOrderDao.getLastPrice(digitalCollection.getId());
            newPrice = ObjectUtil.isNull(newPrice) ? BigDecimal.ZERO : newPrice;
            //藏品发售价
            BigDecimal issuePrice = digitalCollection.getIssuePrice();
            issuePrice = ObjectUtil.isNull(issuePrice) ? BigDecimal.ZERO : issuePrice;

            // 2022年11月7日16:05:51 最新成交价修改
            secondConsignDetailAndListVO.setFinalPrice(digitalCollection.getNewDeal().toPlainString());
            secondConsignDetailAndListVO.setIssuePrice(issuePrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            secondConsignDetailAndListVO.setMinPrice(request.getLowPrice().compareTo(secondCollectionConfig.getMinPrice()) < 0 ?
                    request.getLowPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString() :
                    secondCollectionConfig.getMinPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            secondConsignDetailAndListVO.setMaxPrice(request.getHighPrice().compareTo(secondCollectionConfig.getMaxPrice()) > 0
                    ? request.getHighPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString()
                    : secondCollectionConfig.getMaxPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            secondConsignDetailAndListVO.setSumCount(digitalCollection.getSumCount());
            secondConsignDetailAndListVO.setCollectionListVOList(userCollectionDao.getConsignCollectionListAdmin(UserPool.getUser().getId(), request.getCollectionId(), request.getNum()));
            secondConsignDetailAndListVO.setNewDeal(newDeal.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            // 以上是直接复制来的获取可以寄售的藏品列表内容数据

            //校验价格区间
            if (NumberUtil.isLess(request.getLowPrice(), secondCollectionConfig.getMinPrice()) || NumberUtil.isGreater(request.getLowPrice(), secondCollectionConfig.getMaxPrice())) {
                throw new GlobalRunTimeException("请在可挂售区间内出价");
            }
            if (NumberUtil.isLess(request.getHighPrice(), secondCollectionConfig.getMinPrice()) || NumberUtil.isGreater(request.getHighPrice(), secondCollectionConfig.getMaxPrice())) {
                throw new GlobalRunTimeException("请在可挂售区间内出价");
            }


            // 批量进行上架验证,加锁
            List<ConsignCollectionListVO> collectionListVOList = secondConsignDetailAndListVO.getCollectionListVOList();
            if (CollUtil.isEmpty(collectionListVOList)) {
                return Result.fail("当前上架藏品数量不存在");
            }
            RLock lock = redissonClient.getLock(RedisKeyEnum.CON_SIGN.getKey() + collectionListVOList.get(0));
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                //获取寄售时间 并且判断是否是在寄售时间内
                StaticData staticData = staticDataService.getByType("market_config");
                if (ObjectUtil.isNull(staticData) || StrUtil.isBlank(staticData.getValue())) {
                    return Result.fail(ErrorCode.NOT_ALLOW_DEAL_TIME);
                }
                DateTime now = DateTime.now();
                String dateStr = now.toString("yyyy-MM-dd");
                MarketConfigDTO marketConfigDTO = JSONObject.parseObject(staticData.getValue(), MarketConfigDTO.class);
                DateTime billingStartDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeOne(), "yyyy-MM-dd HH:mm");
                DateTime billingEndDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeOne(), "yyyy-MM-dd HH:mm");
                DateTime billingStartDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeTwo(), "yyyy-MM-dd HH:mm");
                DateTime billingEndDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeTwo(), "yyyy-MM-dd HH:mm");

                if (!((now.after(billingStartDate1) && now.before(billingEndDate1)) || (now.after(billingStartDate2) && now.before(billingEndDate2)))) {
                    return Result.fail(ErrorCode.NOT_ALLOW_DEAL_TIME);
                }

                secondCollectionService.batchConSignForMaintain(collectionListVOList.stream().map(ConsignCollectionListVO::getId).collect(Collectors.toList()), request.getLowPrice(), request.getHighPrice(), userInfo.getTransactionPassword());
            } else {
                throw new GlobalRunTimeException(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(e.getMessage());
        } finally {
            UserPool.clear();
        }

        return Result.success();
    }


    @ApiOperation(value = "自由市场藏品列表", notes = "自由市场藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/freeMarketCollectionList", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<BrandConfigAdminVO>> freeMarketCollectionList(@RequestBody FreeMarketCollectionListRequest request) {
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), request.getCheckedUserId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        return Result.success(secondCollectionConfigDao.freemarketConfigList(request.getCollectionName(), request.getCheckedUserId()));
    }


    @ApiOperation(value = "市值账号可寄售藏品列表", notes = "市值账号可寄售藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/maintainCollectionNow", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<MyCollectionNowListVO>> maintainfreeMarketCollectionList(@RequestBody IdRequest idRequest) {
        if (!marketMaintainDao.verificationBinding(SysMemberPool.getMember().getId(), idRequest.getId())) {
            throw new GlobalRunTimeException("非权限账号");
        }
        return Result.success(userCollectionDao.getMaintainInviteListNow(idRequest.getId()));
    }


    /**
     * 单个下架校验
     */
    private void validMaintainFreeMarketOffShelf(MaintainOffTheShelfRequest request) {

        Assert.notNull(request.getUserCollectionId(), () -> new GlobalRunTimeException("用户藏品id不能为空"));
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号用户id不能为空"));

        Assert.notNull(userCollectionService.getById(request.getUserCollectionId()), () -> new GlobalRunTimeException("用户藏品不存在"));
    }


    /**
     * 批量下架教研
     */
    private void validMaintainFreeMarketBatchOffShelf(MaintainBatchOffTheShelfRequest request) {
        //价格区间字段要么全空 要么都存在
        if (null != request.getLowPrice() || null != request.getHighPrice()) {
            if (null == request.getLowPrice() || null == request.getHighPrice()) {
                throw new GlobalRunTimeException("底价和上限价必须同时存在");
            }
            Assert.isTrue(request.getLowPrice().compareTo(BigDecimal.ZERO) > 0, () -> new GlobalRunTimeException("挂单价格必须大于0"));
            Assert.isTrue(request.getHighPrice().compareTo(BigDecimal.ZERO) > 0, () -> new GlobalRunTimeException("挂单价格必须大于0"));
        }
        Assert.notNull(request.getCollectionId(), () -> new GlobalRunTimeException("藏品id不能为空"));
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号用户id不能为空"));
    }


    /**
     * 批量上架参数校验
     */

    private void validMaintainFreeMarketBatchHitShelf(MaintainBatchOnTheShelfRequest request) {
        //价格区间字段要么全空 要么都存在
        if (null != request.getLowPrice() || null != request.getHighPrice()) {
            if (null == request.getLowPrice() || null == request.getHighPrice()) {
                throw new GlobalRunTimeException("底价和上限价必须同时存在");
            }
            Assert.isTrue(request.getLowPrice().compareTo(BigDecimal.ZERO) > 0, () -> new GlobalRunTimeException("挂单价格必须大于0"));
            Assert.isTrue(request.getHighPrice().compareTo(BigDecimal.ZERO) > 0, () -> new GlobalRunTimeException("挂单价格必须大于0"));
        }
        Assert.notNull(request.getCollectionId(), () -> new GlobalRunTimeException("藏品id不能为空"));
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号用户id不能为空"));


        //藏品是否在共识区
        SearchRelevance relevance = searchRelevanceDao.getRelevanceByCollectionId(request.getCollectionId());
        //上架藏品记录
        MyCollectionNowListVO collection = userCollectionDao.getMaintainCollection(request.getCheckedUserId(), request.getCollectionId());
        if (ObjectUtil.isNull(collection)) {
            throw new GlobalRunTimeException("藏品不存在!");
        }
        if (request.getNum() > collection.getNotPutaway()) {
            throw new GlobalRunTimeException("可寄售数量不足");
        }
        if (relevance.getSearchId() == 9) {
            if (collection.getPutaway() >= 1 || request.getNum() > 1) {
                //共识区用户只能挂一个
                ExitConsensusUser consensusUser = exitConsensusUserDao.getByUserId(request.getCheckedUserId());
                if (ObjectUtil.isNull(consensusUser) || !consensusUser.getStatus()) {
                    throw new GlobalRunTimeException("共识区用户同藏品只能挂售一个!");
                }
            }
        }


    }

    /**
     * 单个上架参数校验
     *
     * @param request
     */
    private void validMaintainFreeMarketHitShelf(MaintainFreeMarketHitShelfRequest request) {
        Assert.notNull(request.getUserCollectionId(), () -> new GlobalRunTimeException("用户藏品id不能为空"));
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号用户id不能为空"));
        Assert.notNull(request.getSalesPrice(), () -> new GlobalRunTimeException("挂单价不能为空"));
        Assert.isTrue(request.getSalesPrice().compareTo(BigDecimal.ZERO) > 0, () -> new GlobalRunTimeException("挂单价格必须大于0"));

        UserCollection userCollection = userCollectionDao.selectByIdAndUserIdAndIsHold(request.getUserCollectionId(), UserPool.getUser().getId());

        //藏品是否在共识区
        SearchRelevance relevance = searchRelevanceDao.getRelevanceByCollectionId(userCollection.getCollectionId());
        //上架藏品记录
        MyCollectionNowListVO collection = userCollectionDao.getMaintainCollection(request.getCheckedUserId(), userCollection.getCollectionId());
        if (ObjectUtil.isNull(collection)) {
            throw new GlobalRunTimeException("藏品不存在!");
        }
        if (collection.getNotPutaway() < 1) {
            throw new GlobalRunTimeException("可寄售数量不足");
        }
        if (relevance.getSearchId() == 9) {
            if (collection.getPutaway() >= 1) {
                //共识区用户只能挂一个
                ExitConsensusUser consensusUser = exitConsensusUserDao.getByUserId(request.getCheckedUserId());
                if (ObjectUtil.isNull(consensusUser) || !consensusUser.getStatus()) {
                    throw new GlobalRunTimeException("共识区用户同藏品只能挂售一个!");
                }
            }
        }
    }


    /**
     * 市值账号持有藏品列表
     *
     * @param request
     */
    private void validMaintainCollectionRequest(MaintainCollectionListRequest request) {
        Assert.notNull(request.getCollectionId(), () -> new GlobalRunTimeException("藏品id不能为空"));
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号用户id不能为空"));
        //价格区间字段要么全空 要么都存在
        if (null != request.getLowPrice() || null != request.getHighPrice()) {
            if (null == request.getLowPrice() || null == request.getHighPrice()) {
                throw new GlobalRunTimeException("底价和上限价必须同时存在");
            }
        }
    }


    /**
     * 批量购买校验
     *
     * @param request
     */
    private void validBatchMaintainSecondCollectionRequest(MaintainBatchSecondCollectionRequest request) {
        Assert.notNull(request.getCollectionId(), () -> new GlobalRunTimeException("藏品id不能为空"));
        Assert.notNull(request.getNum(), () -> new GlobalRunTimeException("购买数量不能为空"));
        Assert.isTrue(request.getNum() <= 10, () -> new GlobalRunTimeException("单次购买数量不能超过10"));
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号用户id不能为空"));
        //价格区间字段要么全空 要么都存在
        if (null != request.getLowPrice() || null != request.getHighPrice()) {
            if (null == request.getLowPrice() || null == request.getHighPrice()) {
                throw new GlobalRunTimeException("底价和上限价必须同时存在");
            }
        }
    }


    /**
     * 是只账号挂单列表基础教研
     *
     * @param request
     * @See maintainCollectionList
     */
    private void validMaintainCollectionListRequest(MaintainSecondCollectionListRequest request) {
        Assert.notNull(request.getCheckedUserId(), () -> new GlobalRunTimeException("当前市值账号不能为空"));
        Assert.notNull(request.getCollectionId(), () -> new GlobalRunTimeException("藏品id不能为空"));
        //价格区间字段要么全空 要么都存在
        if (null != request.getLowPrice() || null != request.getHighPrice()) {
            if (null == request.getLowPrice() || null == request.getHighPrice()) {
                throw new GlobalRunTimeException("底价和上限价必须同时存在");
            }
        }


    }

    /**
     * 二级订单单买校验
     *
     * @param request
     */
    private void validMaintainBuySecondCollectionRequest(MaintainBuySecondCollectionRequest request) {
        if (null == request.getId() || null == request.getCheckedUserId()) {
            throw new GlobalRunTimeException("参数不能为空");
        }
        SecondCollection secondCollection = secondCollectionDao.findById(request.getId());
        Assert.notNull(secondCollection, () -> new GlobalRunTimeException("当前挂单不存在"));
        Assert.isTrue(!Objects.equals(secondCollection.getUserId(), request.getCheckedUserId()), () -> new GlobalRunTimeException("不能购买自己的藏品"));

    }
}
